import java.io.*;

import java.util.*;
import java.text.*;

public class AnalyzeAllFind {

	static String dir="";
	public static String pardir="";
	static PrintWriter outd1=null;
	static PrintWriter outf1=null;
	static PrintWriter outf2=null;
	static PrintWriter ERR;
	static int _id=0;
	static Properties dir_props=new Properties();
	static boolean ignoredirname=true;
	static boolean appendflag=false;
	static int mindirsize=100000;
	static String inputFileName="";
	static String inputFileNameWithSlash="";
	static byte[] inputFileBARR=null;
	public static void main(String[] args) throws Exception{
		if(args.length<1){
			System.out.println("usage : AnalyzeAll1 <dirpath> (ignoredirnameflag) (appendflag)");
			System.out.println("eg 			: AnalyzeAll1 <dirpath> t t");
			System.out.println("default is  : AnalyzeAll1 <dirpath> f f");
			System.exit(0);
		}
		if(args.length>1 && args[1].equals("f"))
			ignoredirname=false;
		if(args.length>2 && args[2].equals("t"))
			appendflag=true;
		if(args.length>3){
			mindirsize=Integer.parseInt(args[3]);
		}

		System.out.println("ignore dir name="+ignoredirname);
		System.out.println("append dir flag="+appendflag);
		System.out.println("par dir="+pardir+".");
		if(!appendflag){
			storeProperties(dir_props);
			String time=new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss").format(new Date());
			Process pc0=Runtime.getRuntime().exec(new String[]{"mkdir","-p",pardir+"run"+time});
			pc0.waitFor();

			Process pc=Runtime.getRuntime().exec(new String[]{"mv","-f",pardir+"tmp/",pardir+"run"+time});
			System.out.println("archived 'tmp' directory"+pc.waitFor()+":");
			if(pardir.length()==0){
				File[] currfiles=new File(".").listFiles();
				for(File curr_fil:currfiles){
					if(curr_fil.getName().startsWith("second") && curr_fil.isDirectory()){
						Process pc__=Runtime.getRuntime().exec(new String[]{"mv","-f",pardir+curr_fil.getName()+"/",pardir+"run"+time});  
						System.out.println("archived 'second' dir :"+pc__.waitFor()+":");
					}
				}
			}
			File[] farr= new File(".").listFiles();
			for(File _ff:farr){
				if(_ff.isFile() && (_ff.getName().endsWith(".log")|| _ff.getName().endsWith(".txt")|| _ff.getName().endsWith(".sh"))){
					Process pc1=Runtime.getRuntime().exec(new String[]{"mv","-f", pardir+_ff.getName(),pardir+"run"+time+"/"});
					pc1.waitFor();
				}
			}

			
		}else{
			try{
				dir_props=loadProperties();
			}catch(Exception e){
				storeProperties(dir_props);
				
			}
		}

		ERR=new PrintWriter(pardir+"ERR.txt");
		File _dir= new File(pardir+"tmp");
		if(!_dir.exists()){
			_dir.mkdirs();
			}
		Set ids=dir_props.keySet();
		for(Object ob:ids){
			if(_id<=Integer.parseInt((String)ob)){
				_id=Integer.parseInt((String)ob)+1;
			}
		}
		
		mains(new String[]{args[0]});

		
		storeProperties(dir_props);
	}

	public static void mains(String[] args) throws Exception{
		if(args.length<1)
			System.exit(0);
		dir=args[0];
		String tree="";
		
		if((new File(dir).isFile())){
			inputFileName=args[0];
			File _inpFle= new File(inputFileName);
			inputFileBARR=new byte[(int)_inpFle.length()];
			FileInputStream _inpis=new FileInputStream(_inpFle);
			int _re=_inpis.read(inputFileBARR);
			_inpis.close();
			if(_re!=inputFileBARR.length){
				System.out.println("error reading "+inputFileName);
				System.exit(0);
			}
				
			inputFileNameWithSlash=inputFileName.replace("__","/");
			dir=dir.replace("__", "/");
			outd1=new PrintWriter(pardir+"."+dir.replace("/", "_=")+".d1.txt");
			outf1=new PrintWriter(pardir+"."+dir.replace("/", "_=")+".f1.txt");
			outf2=new PrintWriter(pardir+"."+dir.replace("/", "_=")+".f2.txt");
			tree=analyzeFDir2(".",0);
		}else{
			File f1 = new File(dir);
			outd1=new PrintWriter(pardir+"."+dir.replace("/", "_=")+".d1.txt");
			outf1=new PrintWriter(pardir+"."+dir.replace("/", "_=")+".f1.txt");
			outf2=new PrintWriter(pardir+"."+dir.replace("/", "_=")+".f2.txt");
			tree=analyzeDir(f1,0).toString();
		}
		long length=Long.parseLong(tree.substring(0,15));
		tree=tree.substring(15);
		outd1.println(encrypt("<"+dir.substring(dir.lastIndexOf("/")+1)+" d=\""+length+"\">"));
		outd1.println(encrypt(tree));
		outd1.println(encrypt("</"+dir.substring(dir.lastIndexOf("/")+1)+">"));
		outd1.close();
		outf1.close();
		outf2.close();
		ERR.close();
			
	}
	
	private static String analyzeFDir2(String dirName,long size) throws Exception{
		String ret="";
		BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(inputFileBARR)));
		String line="";
		StringBuffer sb = new StringBuffer("");
		while((line=br.readLine())!= null){
			if(line.startsWith(dirName+":"))
				break;
		}
		br.readLine();
		while((line=br.readLine())!= null){
			if(line.length()==0)
				break;
			
			line+="\n";
			StringTokenizer stk= new StringTokenizer(line," ");
			if(line.startsWith("d")){
				for(int i=0;i<7;i++)
						stk.nextElement();
				String _dir_name=stk.nextToken("\n").trim();
				if(_dir_name.equals(".") || _dir_name.equals(".."))
					continue;
				String _dir=analyzeFDir2(dirName+"/"+_dir_name,0).toString();
				long _size=Long.parseLong(_dir.substring(0,15));
				StringBuffer ab= new StringBuffer("");
				ab.append("<"+_dir_name.replace(".","___")+" d=\""+_size+"\">\n");
				if(_dir.length()>15)
					ab.append("\n"+_dir.substring(15)+"\n");
				ab.append("</"+_dir_name.replace(".","___")+">\n");
				if(_size>mindirsize){
					int inc=((int)(Math.random()*100))%100;
					if(inc==0)
						inc=1;
					_id+=inc;
					dir_props.put((_id+""), inputFileNameWithSlash+dirName.substring(1)+"/"+_dir_name);
					String _to_write=ab.toString();
					if(ignoredirname){
						int _strrt=_to_write.indexOf("\n");
						int _endd=_to_write.lastIndexOf("\n</");
						if(_strrt<_endd && _strrt >0)
							_to_write=_to_write.substring(_strrt,_endd);
					}
						
					PrintWriter pw = new PrintWriter(new File(pardir+"tmp/"+(999999999999999L-_size)+"_"+(_id)+"_"+(_to_write.length())+".txt"));
					pw.print(encrypt(_to_write));
					pw.close();
				}
				sb.append(ab);
				size+=_size;
				
			}else if(line.startsWith("-")){
				for(int i=0;i<4;i++)
					stk.nextElement();
				String _file_sz=(String)stk.nextElement();
				stk.nextElement();stk.nextElement();
				String fname=stk.nextToken("\n").trim();
				
				long _size=Long.parseLong(_file_sz);
				outf1.println(encrypt(inputFileNameWithSlash+dirName.substring(1)+"/"+fname+ "::"+_file_sz));
				outf2.println(inputFileNameWithSlash+dirName.substring(1)+"/"+fname);
				size+=_size;
				sb.append("<"+fname.replace(".","___")+" f=\""+_size+"\"/>\n");
				
			}
			else {
				System.out.println("NOT FILE/DIR?"+inputFileNameWithSlash+"/"+dirName+"--"+line);
				ERR.println("NOT FILE/DIR?"+inputFileNameWithSlash+"/"+dirName+"--"+line);
				ERR.flush();
			}
		}
		
		outf1.flush();
		outf2.flush();
		String _tmp=""+(1000000000000000L+size);
		sb.insert(0, _tmp.substring(1));
		br.close();
		
		return sb.toString();
	}

	private static StringBuffer analyzeDir(File f1, long size)  throws Exception{
		File[] farr= f1.listFiles();
		String dirName=f1.getAbsolutePath();
		StringBuffer sb = new StringBuffer("");
		if(farr != null){
			TreeSet<String> sortedFiles= new TreeSet<String>();
			for(File f:farr)
				sortedFiles.add(f.getName());
			
			for(String fname:sortedFiles){
				File f= new File(dirName+"/"+fname);
				if(f.isFile()){
					long _size=f.length();
					outf1.println(encrypt(f.getAbsolutePath()+ "::"+_size));
					outf2.println(f.getAbsolutePath());
					size+=_size;
					sb.append("<"+fname.replace(".","___")+" f=\""+_size+"\"/>\n");
				}
				else if(f.isDirectory()){
					String _dir=analyzeDir(f,0).toString();
					long _size=Long.parseLong(_dir.substring(0,15));
					StringBuffer ab= new StringBuffer("");
					ab.append("<"+fname.replace(".","___")+" d=\""+_size+"\">\n");
					if(_dir.length()>15)
						ab.append("\n"+_dir.substring(15)+"\n");
					ab.append("</"+fname.replace(".","___")+">\n");
					if(_size>mindirsize){
						int inc=((int)(Math.random()*100))%100;
						if(inc==0)
							inc=1;
						_id+=inc;
						dir_props.put((_id+""), f.getAbsolutePath());
						String _to_write=ab.toString();
						if(ignoredirname){
							int _strrt=_to_write.indexOf("\n");
							int _endd=_to_write.lastIndexOf("\n</");
							if(_strrt<_endd && _strrt >0)
								_to_write=_to_write.substring(_strrt,_endd);
						}
							
						PrintWriter pw = new PrintWriter(new File(pardir+"tmp/"+(999999999999999L-_size)+"_"+(_id)+"_"+(_to_write.length())+".txt"));
						pw.print(encrypt(_to_write));
						pw.close();
					}
					sb.append(ab);
					size+=_size;
				}
				else {
					System.out.println("NOT FILE/DIR?"+f.getAbsolutePath()+"--");
					ERR.println(f.getAbsolutePath());
					ERR.flush();
				}
			}
		}
		else{
			System.out.println(" :: ERR :: ERR :: ERR");
			System.exit(0);
		}
		outf1.flush();
		outf2.flush();
		String _tmp=""+(1000000000000000L+size);
		sb.insert(0, _tmp.substring(1));
		return sb;
	}

	
	public static void storeProperties(Properties props) throws Exception{
		ByteArrayOutputStream bao= new ByteArrayOutputStream();
		props.storeToXML(bao,"modified-"+new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss").format(new Date()));
		byte[] barr=bao.toByteArray();
		FileOutputStream fos=new FileOutputStream(pardir+".dir.txt");
		ByteArrayInputStream bis= new ByteArrayInputStream(barr);
		Crypto.getInstance().encrypt(bis,fos);
		fos.close();
		bis.close();
		bao.close();

	}
	public static Properties loadProperties() throws Exception{
		ByteArrayOutputStream bao=new ByteArrayOutputStream();
		FileInputStream fis=new FileInputStream(pardir+".dir.txt");
		Crypto.getInstance().decrypt(fis, bao);
		byte[] barr=bao.toByteArray();
		ByteArrayInputStream bis= new ByteArrayInputStream(barr);
		Properties props= new Properties();
		props.loadFromXML(bis);
		bao.close();
		fis.close();
		return props;
	}
	
	public static String encrypt(String str){
		return Crypto.getInstance().encrypt(str);
	}
	public static String decrypt(String str){
		return Crypto.getInstance().decrypt(str);
	}
}
